#include "stdafx.h"
#include "gp_Trsf.h"
#include "gp_Vec.h"
#include "gp_XYZ.h"
#include "gp_Ax1.h"
#include "gp_Ax2.h"
#include "gp_Trsf.h"
#include "gp_Vec.h"
#include "gp_Pnt.h"
#include "gp_Dir.h"
#include "gp.h"

void gp_Pnt::Transform (const gp_Trsf& T)
{
	if (T.Form() == gp_Identity) { }
	else if (T.Form() == gp_Translation) { coord.Add (T.TranslationPart ()); }
	else if (T.Form() == gp_Scale) {
		coord.Multiply (T.ScaleFactor ());
		coord.Add      (T.TranslationPart ());
	}
	else if(T.Form() == gp_PntMirror) {
		coord.Reverse ();
		coord.Add     (T.TranslationPart ());
	}
	else { T.Transforms(coord); }
}

void gp_Pnt::Mirror (const gp_Pnt& P)
{
	coord.Reverse ();
	gp_XYZ XYZ = P.coord;
	XYZ.Multiply (2.0);
	coord.Add      (XYZ);
}

gp_Pnt gp_Pnt::Mirrored (const gp_Pnt& P) const
{
	gp_Pnt Pres = *this;
	Pres.Mirror (P);
	return Pres;
}

void gp_Pnt::Mirror (const gp_Ax1& A1)
{
	gp_Trsf T;
	T.SetMirror  (A1);
	T.Transforms (coord);
}

gp_Pnt gp_Pnt::Mirrored (const gp_Ax1& A1) const
{
	gp_Pnt P = *this;
	P.Mirror (A1);
	return P;
}

void gp_Pnt::Mirror (const gp_Ax2& A2)
{
	gp_Trsf T;
	T.SetMirror  (A2);
	T.Transforms (coord);
}

gp_Pnt gp_Pnt::Mirrored (const gp_Ax2& A2) const
{
	gp_Pnt P = *this;
	P.Mirror (A2);
	return P;
}
 gp_Pnt::gp_Pnt() { }

 gp_Pnt::gp_Pnt (const gp_XYZ& Coordinates) : coord (Coordinates)
{ }

 gp_Pnt::gp_Pnt (const double Xp,
		       const double Yp,
		       const double Zp) : coord(Xp, Yp,Zp)
{ }

 void gp_Pnt::SetCoord (const int Index,
			      const double Xi)
{ coord.SetCoord (Index, Xi); }

 void gp_Pnt::SetCoord (const double Xp, 
			      const double Yp, 
			      const double Zp) {
  coord.SetCoord (Xp, Yp, Zp);
}

 void gp_Pnt::SetX (const double X)
{ coord.SetX (X); }

 void gp_Pnt::SetY (const double Y)
{ coord.SetY (Y); }

 void gp_Pnt::SetZ (const double Z)
{ coord.SetZ (Z); }

 void gp_Pnt::SetXYZ (const gp_XYZ& Coordinates) 
{ coord = Coordinates; }

 double gp_Pnt::Coord (const int Index) const
{ return coord.Coord(Index); }

 void gp_Pnt::Coord (double& Xp, 
			   double& Yp, 
			   double& Zp) const { 
			     coord.Coord (Xp, Yp, Zp);
			   }

 double gp_Pnt::X() const
{ return coord.X(); }

 double gp_Pnt::Y() const
{ return coord.Y(); }

 double gp_Pnt::Z() const
{ return coord.Z(); }

 const gp_XYZ& gp_Pnt::XYZ () const
{ return coord; }

 const gp_XYZ& gp_Pnt::Coord () const
{ return coord; }

 gp_XYZ& gp_Pnt::ChangeCoord ()
{ return coord; }

 void gp_Pnt::BaryCenter(const double A,
			       const gp_Pnt& P,
			       const double B)
{
  coord.SetLinearForm(A,coord,B,P.coord);
  coord.Divide(A + B);
}

 bool gp_Pnt::IsEqual
(const gp_Pnt& Other,
 const double LinearTolerance) const
{ return Distance (Other) <= LinearTolerance; }

 double gp_Pnt::Distance (const gp_Pnt& Other) const
{
  double d=0,dd;
  const gp_XYZ& XYZ = Other.coord;
  dd = coord.X(); dd -= XYZ.X(); dd *= dd; d += dd;
  dd = coord.Y(); dd -= XYZ.Y(); dd *= dd; d += dd;
  dd = coord.Z(); dd -= XYZ.Z(); dd *= dd; d += dd;
  return(sqrt(d));
}

 double gp_Pnt::SquareDistance (const gp_Pnt& Other) const
{
  double d=0,dd;
  const gp_XYZ& XYZ = Other.coord;
  dd = coord.X(); dd -= XYZ.X(); dd *= dd; d += dd;
  dd = coord.Y(); dd -= XYZ.Y(); dd *= dd; d += dd;
  dd = coord.Z(); dd -= XYZ.Z(); dd *= dd; d += dd;
  return(d);
}

 void gp_Pnt::Rotate (const gp_Ax1& A1,
			    const double Ang)
{
  gp_Trsf T;
  T.SetRotation (A1, Ang);
  T.Transforms  (coord);
}

 gp_Pnt gp_Pnt::Rotated (const gp_Ax1& A1,
			       const double Ang) const
{
  gp_Pnt P = *this;
  P.Rotate (A1, Ang);
  return P;
}

 void gp_Pnt::Scale (const gp_Pnt& P,
			   const double S)
{
  gp_XYZ XYZ = P.coord;
  XYZ.Multiply (1.0 - S);
  coord.Multiply (S);
  coord.Add      (XYZ);
}

 gp_Pnt gp_Pnt::Scaled (const gp_Pnt& P,
			      const double S)  const
{
  gp_Pnt Pres = *this;
  Pres.Scale (P, S);
  return Pres;
}

 gp_Pnt gp_Pnt::Transformed (const gp_Trsf& T) const
{
  gp_Pnt P = *this;
  P.Transform (T);
  return P;
}

 void gp_Pnt::Translate (const gp_Vec& V)
{ coord.Add (V.XYZ()); }

 gp_Pnt gp_Pnt::Translated (const gp_Vec& V) const
{
  gp_Pnt P = *this;
  P.coord.Add (V.XYZ());
  return P;
}


 gp_Pnt gp_Pnt::Moved(const gp_Dir& D,double length)
 {	
	double dX = D.X()*length;
	double dY = D.Y()*length;
	double dZ = D.Z()*length;

	return gp_Pnt(this->X()+dX,this->Y()+dY,this->Z()+dZ);	
 }

 void gp_Pnt::Translate (const gp_Pnt& P1,
			       const gp_Pnt& P2)
{
  coord.Add      (P2.coord);
  coord.Subtract (P1.coord);
}               

 gp_Pnt gp_Pnt::Translated (const gp_Pnt& P1,
				  const gp_Pnt& P2) const
{
  gp_Pnt P = *this;
  P.Translate (P1 , P2);
  return P;
}               

